/*
 This file '_accordion' is part of Firebird Integrated Solution 1.0

 Copyright (c) 2015 Lincong

 Contact:  
 Email: lincong1987@gmail.com

 QQ: 159257119

 See Usage at http://www.jplatformx.com/firebird

 Create date: 2015-07-14 04:42
 */


(function ($, undefined) {

	var uid = 0,
		hideProps = {},
		showProps = {};

	hideProps.height = hideProps.paddingTop = hideProps.paddingBottom =
		hideProps.borderTopWidth = hideProps.borderBottomWidth = "hide";
	showProps.height = showProps.paddingTop = showProps.paddingBottom =
		showProps.borderTopWidth = showProps.borderBottomWidth = "show";

	$.widget("ui.accordion", {
		version: "1.9.2",
		options: {
			active: 0,
			animate: {},
			collapsible: false,
			event: "click",
			header: "> li > :first-child,> :not(li):even",
			heightStyle: "auto",
			icons: {
				activeHeader: "ui-icon-triangle-1-s",
				header: "ui-icon-triangle-1-e"
			},

			// callbacks
			activate: null,
			beforeActivate: null
		},

		_create: function () {
			var accordionId = this.accordionId = "ui-accordion-" +
					(this.element.attr("id") || ++uid),
				options = this.options;

			this.prevShow = this.prevHide = $();
			this.element.addClass("ui-accordion ui-widget ui-helper-reset");

			this.headers = this.element.find(options.header)
				.addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all");
			this._hoverable(this.headers);
			this._focusable(this.headers);

			this.headers.next()
				.addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom")
				.hide();

			// don't allow collapsible: false and active: false / null
			if (!options.collapsible && (options.active === false || options.active == null)) {
				options.active = 0;
			}
			// handle negative values
			if (options.active < 0) {
				options.active += this.headers.length;
			}
			this.active = this._findActive(options.active)
				.addClass("ui-accordion-header-active ui-state-active")
				.toggleClass("ui-corner-all ui-corner-top");
			this.active.next()
				.addClass("ui-accordion-content-active")
				.show();

			this._createIcons();
			this.refresh();

			// ARIA
			this.element.attr("role", "tablist");

			this.headers
				.attr("role", "tab")
				.each(function (i) {
					var header = $(this),
						headerId = header.attr("id"),
						panel = header.next(),
						panelId = panel.attr("id");
					if (!headerId) {
						headerId = accordionId + "-header-" + i;
						header.attr("id", headerId);
					}
					if (!panelId) {
						panelId = accordionId + "-panel-" + i;
						panel.attr("id", panelId);
					}
					header.attr("aria-controls", panelId);
					panel.attr("aria-labelledby", headerId);
				})
				.next()
				.attr("role", "tabpanel");

			this.headers
				.not(this.active)
				.attr({
					"aria-selected": "false",
					tabIndex: -1
				})
				.next()
				.attr({
					"aria-expanded": "false",
					"aria-hidden": "true"
				})
				.hide();

			// make sure at least one header is in the tab order
			if (!this.active.length) {
				this.headers.eq(0).attr("tabIndex", 0);
			} else {
				this.active.attr({
					"aria-selected": "true",
					tabIndex: 0
				})
					.next()
					.attr({
						"aria-expanded": "true",
						"aria-hidden": "false"
					});
			}

			this._on(this.headers, {keydown: "_keydown"});
			this._on(this.headers.next(), {keydown: "_panelKeyDown"});
			this._setupEvents(options.event);
		},

		_getCreateEventData: function () {
			return {
				header: this.active,
				content: !this.active.length ? $() : this.active.next()
			};
		},

		_createIcons: function () {
			var icons = this.options.icons;
			if (icons) {
				$("<span>")
					.addClass("ui-accordion-header-icon ui-icon " + icons.header)
					.prependTo(this.headers);
				this.active.children(".ui-accordion-header-icon")
					.removeClass(icons.header)
					.addClass(icons.activeHeader);
				this.headers.addClass("ui-accordion-icons");
			}
		},

		_destroyIcons: function () {
			this.headers
				.removeClass("ui-accordion-icons")
				.children(".ui-accordion-header-icon")
				.remove();
		},

		_destroy: function () {
			var contents;

			// clean up main element
			this.element
				.removeClass("ui-accordion ui-widget ui-helper-reset")
				.removeAttr("role");

			// clean up headers
			this.headers
				.removeClass("ui-accordion-header ui-accordion-header-active ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top")
				.removeAttr("role")
				.removeAttr("aria-selected")
				.removeAttr("aria-controls")
				.removeAttr("tabIndex")
				.each(function () {
					if (/^ui-accordion/.test(this.id)) {
						this.removeAttribute("id");
					}
				});
			this._destroyIcons();

			// clean up content panels
			contents = this.headers.next()
				.css("display", "")
				.removeAttr("role")
				.removeAttr("aria-expanded")
				.removeAttr("aria-hidden")
				.removeAttr("aria-labelledby")
				.removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled")
				.each(function () {
					if (/^ui-accordion/.test(this.id)) {
						this.removeAttribute("id");
					}
				});
			if (this.options.heightStyle !== "content") {
				contents.css("height", "");
			}
		},

		_setOption: function (key, value) {
			if (key === "active") {
				// _activate() will handle invalid values and update this.options
				this._activate(value);
				return;
			}

			if (key === "event") {
				if (this.options.event) {
					this._off(this.headers, this.options.event);
				}
				this._setupEvents(value);
			}

			this._super(key, value);

			// setting collapsible: false while collapsed; open first panel
			if (key === "collapsible" && !value && this.options.active === false) {
				this._activate(0);
			}

			if (key === "icons") {
				this._destroyIcons();
				if (value) {
					this._createIcons();
				}
			}

			// #5332 - opacity doesn't cascade to positioned elements in IE
			// so we need to add the disabled class to the headers and panels
			if (key === "disabled") {
				this.headers.add(this.headers.next())
					.toggleClass("ui-state-disabled", !!value);
			}
		},

		_keydown: function (event) {
			if (event.altKey || event.ctrlKey) {
				return;
			}

			var keyCode = $.ui.keyCode,
				length = this.headers.length,
				currentIndex = this.headers.index(event.target),
				toFocus = false;

			switch (event.keyCode) {
				case keyCode.RIGHT:
				case keyCode.DOWN:
					toFocus = this.headers[( currentIndex + 1 ) % length];
					break;
				case keyCode.LEFT:
				case keyCode.UP:
					toFocus = this.headers[( currentIndex - 1 + length ) % length];
					break;
				case keyCode.SPACE:
				case keyCode.ENTER:
					this._eventHandler(event);
					break;
				case keyCode.HOME:
					toFocus = this.headers[0];
					break;
				case keyCode.END:
					toFocus = this.headers[length - 1];
					break;
			}

			if (toFocus) {
				$(event.target).attr("tabIndex", -1);
				$(toFocus).attr("tabIndex", 0);
				toFocus.focus();
				event.preventDefault();
			}
		},

		_panelKeyDown: function (event) {
			if (event.keyCode === $.ui.keyCode.UP && event.ctrlKey) {
				$(event.currentTarget).prev().focus();
			}
		},

		refresh: function () {
			var maxHeight, overflow,
				heightStyle = this.options.heightStyle,
				parent = this.element.parent();

			if (heightStyle === "fill") {
				// IE 6 treats height like minHeight, so we need to turn off overflow
				// in order to get a reliable height
				// we use the minHeight support test because we assume that only
				// browsers that don't support minHeight will treat height as minHeight
				if (!$.support.minHeight) {
					overflow = parent.css("overflow");
					parent.css("overflow", "hidden");
				}
				maxHeight = parent.height();
				this.element.siblings(":visible").each(function () {
					var elem = $(this),
						position = elem.css("position");

					if (position === "absolute" || position === "fixed") {
						return;
					}
					maxHeight -= elem.outerHeight(true);
				});
				if (overflow) {
					parent.css("overflow", overflow);
				}

				this.headers.each(function () {
					maxHeight -= $(this).outerHeight(true);
				});

				this.headers.next()
					.each(function () {
						$(this).height(Math.max(0, maxHeight -
							$(this).innerHeight() + $(this).height()));
					})
					.css("overflow", "auto");
			} else if (heightStyle === "auto") {
				maxHeight = 0;
				this.headers.next()
					.each(function () {
						maxHeight = Math.max(maxHeight, $(this).css("height", "").height());
					})
					.height(maxHeight);
			}
		},

		_activate: function (index) {
			var active = this._findActive(index)[0];

			// trying to activate the already active panel
			if (active === this.active[0]) {
				return;
			}

			// trying to collapse, simulate a click on the currently active header
			active = active || this.active[0];

			this._eventHandler({
				target: active,
				currentTarget: active,
				preventDefault: $.noop
			});
		},

		_findActive: function (selector) {
			return typeof selector === "number" ? this.headers.eq(selector) : $();
		},

		_setupEvents: function (event) {
			var events = {};
			if (!event) {
				return;
			}
			$.each(event.split(" "), function (index, eventName) {
				events[eventName] = "_eventHandler";
			});
			this._on(this.headers, events);
		},

		_eventHandler: function (event) {
			var options = this.options,
				active = this.active,
				clicked = $(event.currentTarget),
				clickedIsActive = clicked[0] === active[0],
				collapsing = clickedIsActive && options.collapsible,
				toShow = collapsing ? $() : clicked.next(),
				toHide = active.next(),
				eventData = {
					oldHeader: active,
					oldPanel: toHide,
					newHeader: collapsing ? $() : clicked,
					newPanel: toShow
				};

			event.preventDefault();

			if (
				// click on active header, but not collapsible
			( clickedIsActive && !options.collapsible ) ||
				// allow canceling activation
			( this._trigger("beforeActivate", event, eventData) === false )) {
				return;
			}

			options.active = collapsing ? false : this.headers.index(clicked);

			// when the call to ._toggle() comes after the class changes
			// it causes a very odd bug in IE 8 (see #6720)
			this.active = clickedIsActive ? $() : clicked;
			this._toggle(eventData);

			// switch classes
			// corner classes on the previously active header stay after the animation
			active.removeClass("ui-accordion-header-active ui-state-active");
			if (options.icons) {
				active.children(".ui-accordion-header-icon")
					.removeClass(options.icons.activeHeader)
					.addClass(options.icons.header);
			}

			if (!clickedIsActive) {
				clicked
					.removeClass("ui-corner-all")
					.addClass("ui-accordion-header-active ui-state-active ui-corner-top");
				if (options.icons) {
					clicked.children(".ui-accordion-header-icon")
						.removeClass(options.icons.header)
						.addClass(options.icons.activeHeader);
				}

				clicked
					.next()
					.addClass("ui-accordion-content-active");
			}
		},

		_toggle: function (data) {
			var toShow = data.newPanel,
				toHide = this.prevShow.length ? this.prevShow : data.oldPanel;

			// handle activating a panel during the animation for another activation
			this.prevShow.add(this.prevHide).stop(true, true);
			this.prevShow = toShow;
			this.prevHide = toHide;

			if (this.options.animate) {
				this._animate(toShow, toHide, data);
			} else {
				toHide.hide();
				toShow.show();
				this._toggleComplete(data);
			}

			toHide.attr({
				"aria-expanded": "false",
				"aria-hidden": "true"
			});
			toHide.prev().attr("aria-selected", "false");
			// if we're switching panels, remove the old header from the tab order
			// if we're opening from collapsed state, remove the previous header from the tab order
			// if we're collapsing, then keep the collapsing header in the tab order
			if (toShow.length && toHide.length) {
				toHide.prev().attr("tabIndex", -1);
			} else if (toShow.length) {
				this.headers.filter(function () {
					return $(this).attr("tabIndex") === 0;
				})
					.attr("tabIndex", -1);
			}

			toShow
				.attr({
					"aria-expanded": "true",
					"aria-hidden": "false"
				})
				.prev()
				.attr({
					"aria-selected": "true",
					tabIndex: 0
				});
		},

		_animate: function (toShow, toHide, data) {
			var total, easing, duration,
				that = this,
				adjust = 0,
				down = toShow.length &&
					( !toHide.length || ( toShow.index() < toHide.index() ) ),
				animate = this.options.animate || {},
				options = down && animate.down || animate,
				complete = function () {
					that._toggleComplete(data);
				};

			if (typeof options === "number") {
				duration = options;
			}
			if (typeof options === "string") {
				easing = options;
			}
			// fall back from options to animation in case of partial down settings
			easing = easing || options.easing || animate.easing;
			duration = duration || options.duration || animate.duration;

			if (!toHide.length) {
				return toShow.animate(showProps, duration, easing, complete);
			}
			if (!toShow.length) {
				return toHide.animate(hideProps, duration, easing, complete);
			}

			total = toShow.show().outerHeight();
			toHide.animate(hideProps, {
				duration: duration,
				easing: easing,
				step: function (now, fx) {
					fx.now = Math.round(now);
				}
			});
			toShow
				.hide()
				.animate(showProps, {
					duration: duration,
					easing: easing,
					complete: complete,
					step: function (now, fx) {
						fx.now = Math.round(now);
						if (fx.prop !== "height") {
							adjust += fx.now;
						} else if (that.options.heightStyle !== "content") {
							fx.now = Math.round(total - toHide.outerHeight() - adjust);
							adjust = 0;
						}
					}
				});
		},

		_toggleComplete: function (data) {
			var toHide = data.oldPanel;

			toHide
				.removeClass("ui-accordion-content-active")
				.prev()
				.removeClass("ui-corner-top")
				.addClass("ui-corner-all");

			// Work around for rendering bug in IE (#5421)
			if (toHide.length) {
				toHide.parent()[0].className = toHide.parent()[0].className;
			}

			this._trigger("activate", null, data);
		}
	});

// DEPRECATED
	if ($.uiBackCompat !== false) {
		// navigation options
		(function ($, prototype) {
			$.extend(prototype.options, {
				navigation: false,
				navigationFilter: function () {
					return this.href.toLowerCase() === location.href.toLowerCase();
				}
			});

			var _create = prototype._create;
			prototype._create = function () {
				if (this.options.navigation) {
					var that = this,
						headers = this.element.find(this.options.header),
						content = headers.next(),
						current = headers.add(content)
							.find("a")
							.filter(this.options.navigationFilter)
							[0];
					if (current) {
						headers.add(content).each(function (index) {
							if ($.contains(this, current)) {
								that.options.active = Math.floor(index / 2);
								return false;
							}
						});
					}
				}
				_create.call(this);
			};
		}(jQuery, jQuery.ui.accordion.prototype) );

		// height options
		(function ($, prototype) {
			$.extend(prototype.options, {
				heightStyle: null, // remove default so we fall back to old values
				autoHeight: true, // use heightStyle: "auto"
				clearStyle: false, // use heightStyle: "content"
				fillSpace: false // use heightStyle: "fill"
			});

			var _create = prototype._create,
				_setOption = prototype._setOption;

			$.extend(prototype, {
				_create: function () {
					this.options.heightStyle = this.options.heightStyle ||
						this._mergeHeightStyle();

					_create.call(this);
				},

				_setOption: function (key) {
					if (key === "autoHeight" || key === "clearStyle" || key === "fillSpace") {
						this.options.heightStyle = this._mergeHeightStyle();
					}
					_setOption.apply(this, arguments);
				},

				_mergeHeightStyle: function () {
					var options = this.options;

					if (options.fillSpace) {
						return "fill";
					}

					if (options.clearStyle) {
						return "content";
					}

					if (options.autoHeight) {
						return "auto";
					}
				}
			});
		}(jQuery, jQuery.ui.accordion.prototype) );

		// icon options
		(function ($, prototype) {
			$.extend(prototype.options.icons, {
				activeHeader: null, // remove default so we fall back to old values
				headerSelected: "ui-icon-triangle-1-s"
			});

			var _createIcons = prototype._createIcons;
			prototype._createIcons = function () {
				if (this.options.icons) {
					this.options.icons.activeHeader = this.options.icons.activeHeader ||
						this.options.icons.headerSelected;
				}
				_createIcons.call(this);
			};
		}(jQuery, jQuery.ui.accordion.prototype) );

		// expanded active option, activate method
		(function ($, prototype) {
			prototype.activate = prototype._activate;

			var _findActive = prototype._findActive;
			prototype._findActive = function (index) {
				if (index === -1) {
					index = false;
				}
				if (index && typeof index !== "number") {
					index = this.headers.index(this.headers.filter(index));
					if (index === -1) {
						index = false;
					}
				}
				return _findActive.call(this, index);
			};
		}(jQuery, jQuery.ui.accordion.prototype) );

		// resize method
		jQuery.ui.accordion.prototype.resize = jQuery.ui.accordion.prototype.refresh;

		// change events
		(function ($, prototype) {
			$.extend(prototype.options, {
				change: null,
				changestart: null
			});

			var _trigger = prototype._trigger;
			prototype._trigger = function (type, event, data) {
				var ret = _trigger.apply(this, arguments);
				if (!ret) {
					return false;
				}

				if (type === "beforeActivate") {
					ret = _trigger.call(this, "changestart", event, {
						oldHeader: data.oldHeader,
						oldContent: data.oldPanel,
						newHeader: data.newHeader,
						newContent: data.newPanel
					});
				} else if (type === "activate") {
					ret = _trigger.call(this, "change", event, {
						oldHeader: data.oldHeader,
						oldContent: data.oldPanel,
						newHeader: data.newHeader,
						newContent: data.newPanel
					});
				}
				return ret;
			};
		}(jQuery, jQuery.ui.accordion.prototype) );

		// animated option
		// NOTE: this only provides support for "slide", "bounceslide", and easings
		// not the full $.ui.accordion.animations API
		(function ($, prototype) {
			$.extend(prototype.options, {
				animate: null,
				animated: "slide"
			});

			var _create = prototype._create;
			prototype._create = function () {
				var options = this.options;
				if (options.animate === null) {
					if (!options.animated) {
						options.animate = false;
					} else if (options.animated === "slide") {
						options.animate = 300;
					} else if (options.animated === "bounceslide") {
						options.animate = {
							duration: 200,
							down: {
								easing: "easeOutBounce",
								duration: 1000
							}
						};
					} else {
						options.animate = options.animated;
					}
				}

				_create.call(this);
			};
		}(jQuery, jQuery.ui.accordion.prototype) );
	}

})(jQuery);